<?php

namespace app\utils\base\helper;

class Ltcms_zip
{
    static public $errorMsg="";

    /**
     * 获取文件列表
     * @param $startDate
     * @param $endDate
     */
    public static function files($dir)
    {
        return $dir?glob("{$dir}/{,.}[!.,!..]*",GLOB_BRACE):array();
    }

    /**
     * 删除目录
     */
    public static function removeDir($dir)
    {
        if(is_file($dir)){
            return false;
        }
        $fileList=glob("{$dir}/{,.}[!.,!..]*",GLOB_BRACE);
        if($fileList){
            foreach($fileList as $file){
                if(is_dir($file)){
                    self::removeDir($file);
                }else if(is_file($file)){
                    @unlink($file);
                }
            }
        }
        @rmdir($dir);
        return true;
    }

    /**
     * 递归添加文件
     * @param $startDate
     * @param $endDate
     */
    public static function diffFiles($dir1,$dir2,$handleDir="",$files=array())
    {
        $handleDir=$handleDir?$handleDir:$dir1;
        $fileList=glob("{$handleDir}/{,.}[!.,!..]*",GLOB_BRACE);
        if($fileList){
            foreach($fileList as $file){
                if(is_dir($file)){
                    $files=self::diffFiles($dir1,$dir2,$file,$files);
                }else{
                    if(is_file($file)){
                        $file2=str_replace($dir1,$dir2,$file);
                        if(is_file($file2)){
                            $fileMd5=md5_file($file);
                            $file2Md5=md5_file($file2);
                            if($fileMd5 != $file2Md5){
                                $files["new"][]=$file;
                                $files["old"][]=$file2;
                            }
                        }else{
                            $files["new"][]=$file;
                        }
                    }
                }
            }
        }
        return $files;
    }

    /**
     * 递归获取MD5
     * @param $startDate
     * @param $endDate
     */
    public static function getMd5ByConfig($baseDir,$packConfig,$ignoreFile=array(),$handleDir="",$filter=array(),$files=array())
    {
        if(empty($filter) && !$handleDir){
            $baseMd5=md5($baseDir);
            $filter=isset($packConfig[$baseMd5]["child"])?$packConfig[$baseMd5]["child"]:array();
        }
        $packDir=$handleDir?$handleDir:$baseDir;
        $fileList=glob("{$packDir}/{,.}[!.,!..]*",GLOB_BRACE);
        if($fileList){
            foreach($fileList as $file){
                $fileMd5=md5($file);
                if(is_dir($file)){
                    $child=isset($packConfig[$fileMd5]["child"])?$packConfig[$fileMd5]["child"]:array();
                    if($filter){
                        if(in_array($file,$filter)){
                            $files=self::getMd5ByConfig($baseDir,$packConfig,$ignoreFile,$file,$child,$files);
                        }
                    }else{
                        $files=self::getMd5ByConfig($baseDir,$packConfig,$ignoreFile,$file,$child,$files);
                    }
                }else{
                    if(is_file($file)){
                        $fileFileMd5=md5_file($file);
                        $fileHandle=str_replace($baseDir,"",$file);
                        if($filter){
                            if(in_array($file,$filter)){
                                //md5
                                if($ignoreFile && in_array($fileHandle,$ignoreFile)){
                                    continue;
                                }
                                $files[]=$fileHandle."|".$fileFileMd5;
                            }
                        }else{
                            //MD5
                            if($ignoreFile && in_array($fileHandle,$ignoreFile)){
                                continue;
                            }
                            $files[]=$fileHandle."|".$fileFileMd5;
                        }
                    }
                }
            }
        }
        return $files;
    }

    /**
     * 递归添加文件
     * @param $startDate
     * @param $endDate
     */
    public static function resAddFile($zip,$baseDir,$packConfig,$handleDir="",$filter=array())
    {
        if(empty($filter) && !$handleDir){
            $baseMd5=md5($baseDir);
            $filter=isset($packConfig[$baseMd5]["child"])?$packConfig[$baseMd5]["child"]:array();
        }
        $packDir=$handleDir?$handleDir:$baseDir;
        $fileList=glob("{$packDir}/{,.}[!.,!..]*",GLOB_BRACE);
        if($fileList){
            foreach($fileList as $file){
                $fileMd5=md5($file);
                if(is_dir($file)){
                    $child=isset($packConfig[$fileMd5]["child"])?$packConfig[$fileMd5]["child"]:array();
                    if($filter){
                        if(in_array($file,$filter)){
                            $ok=self::resAddFile($zip,$baseDir,$packConfig,$file,$child);
                            if(!$ok){
                                return false;
                            }
                        }
                    }else{
                        $ok=self::resAddFile($zip,$baseDir,$packConfig,$file,$child);
                        if(!$ok){
                            return false;
                        }
                    }
                }else{
                    if(is_file($file)){
                        if($filter){
                            if(in_array($file,$filter)){
                                $addFileOk=$zip->addFile($file, trim(str_replace($baseDir,"",$file),"/\\"));
                                if(!$addFileOk){
                                    return false;
                                }
                            }
                        }else{
                            $addFileOk=$zip->addFile($file, trim(str_replace($baseDir,"",$file),"/\\"));
                            if(!$addFileOk){
                                return false;
                            }
                        }
                    }
                }
            }
        }
        return true;
    }

    /**
     * 根据配置文件获取数据
     * @param $startDate
     * @param $endDate
     */
    public static function getFileByConfig($baseDir,$packConfig,$handle="",$filter=array())
    {
        if(empty($filter)){
            if(!$handle){
                $baseMd5=md5($baseDir);
                $filter=isset($packConfig[$baseMd5]["child"])?$packConfig[$baseMd5]["child"]:array();
            }
        }
        $handle=$handle?$handle:$baseDir;
        $fileList=glob("{$handle}/{,.}[!.,!..]*",GLOB_BRACE);
        $files=array();
        if($fileList){
            foreach($fileList as $file){
                $fileMd5=md5($file);
                if(is_dir($file)){
                    $tmp=array();
                    $tmp["file"]=$file;
                    $tmp["checked"]=0;
                    if($filter && in_array($file,$filter)){
                        $tmp["checked"]=1;
                    }

                    $child=isset($packConfig[$fileMd5]["child"])?$packConfig[$fileMd5]["child"]:array();
                    if($child){
                        $tmp["child"]=self::getFileByConfig($baseDir,$packConfig,$file,$child);
                    }
                    $files[]=$tmp;
                }else{
                    if(is_file($file)){
                        $tmp=array();
                        $tmp["file"]=$file;
                        $tmp["checked"]=0;
                        if($filter && in_array($file,$filter)){
                            $tmp["checked"]=1;
                        }
                        $files[]=$tmp;
                    }
                }
            }
        }
        return $files;
    }

    /**
     * 压缩数据 by 文件列表
     * @param $startDate
     * @param $endDate
     */
    public static function compressByFiles($zipFile,$baseDir,$fileList)
    {
        if($fileList){
            $dir=dirname($zipFile);
            if(!is_dir($dir)){
                mkdir($dir,0775,true);
            }
            if(is_file($zipFile)){
                unlink($zipFile);
            }
            $zip = new \ZipArchive();
            $ok=$zip->open($zipFile, \ZipArchive::CREATE);
            if($ok===true){
                foreach($fileList as $file){
                    if(is_file($file)){
                        $addFileOk=$zip->addFile($file, trim(str_replace($baseDir,"",$file),"/\\"));
                        if(!$addFileOk){
                            return false;
                        }
                    }
                }
                $zip->close();
            }else{
                self::$errorMsg=$zip->getStatusString(); //错误信息
                return false;
            }
            return true;
        }
        return false;
    }

    /**
     * 压缩数据
     * @param $startDate
     * @param $endDate
     */
    public static function compress($packDir,$packConfig,$zipFile)
    {
        $dir=dirname($zipFile);
        if(!is_dir($dir)){
            mkdir($dir,0775,true);
        }
        $zip = new \ZipArchive();
        $ok=$zip->open($zipFile, \ZipArchive::CREATE);
        if($ok===true){
            $addOk=self::resAddFile($zip,$packDir,$packConfig);
            if($addOk){
                $zip->close();
            }else{
                return false;
            }
        }else{
            self::$errorMsg=$zip->getStatusString(); //错误信息
            return false;
        }
        return true;
    }

    /**
     * 获取文件夹MD5列表
     * @param $startDate
     * @param $endDate
     */
    public static function getMd5List($baseDir,$ignoreFile=array(),$handleDir="",$files=array())
    {
        $dir=$handleDir?$handleDir:$baseDir;
        if(is_file($dir)){
            return $files;
        }
        $fileList=glob("{$dir}/{,.}[!.,!..]*",GLOB_BRACE);
        if($fileList){
            foreach($fileList as $file){
                if(is_dir($file)){
                    $files=self::getMd5List($baseDir,$ignoreFile,$file,$files);
                }else if(is_file($file)){
                    $fileHandle=str_replace($baseDir,"",$file);
                    if($ignoreFile && in_array($fileHandle,$ignoreFile)){
                        continue;
                    }
                    $files[]=$fileHandle."|".md5_file($file);
                }
            }
        }
        return $files;
    }

    /**
     * 追加文件To zip
     * @param $startDate
     * @param $endDate
     */
    public static function appendFileByFile($zipFile,$fileList,$baseDir)
    {
        $zip = new \ZipArchive();
        $ok=$zip->open($zipFile);
        if($ok===true){
            if($fileList){
                foreach($fileList as $val){
                    $addOk=$zip->addFile($val, trim(str_replace($baseDir,"",$val),"/\\"));
                    if(!$addOk){
                        return false;
                    }
                }
            }
        }else{
            self::$errorMsg=$zip->getStatusString(); //错误信息
            return false;
        }
        return true;
    }

    /**
     * 追加文件To zip
     * @param $startDate
     * @param $endDate
     */
    public static function appendFile($zipFile,$fileName,$fileStr)
    {
        $zip = new \ZipArchive();
        $ok=$zip->open($zipFile);
        if($ok===true){
            $addOk=$zip->addFromString($fileName,$fileStr);
            if($addOk){
                $zip->close();
            }else{
                return false;
            }
        }else{
            self::$errorMsg=$zip->getStatusString(); //错误信息
            return false;
        }
        return true;
    }

    /**
     * 解压数据
     * @param $startDate
     * @param $endDate
     */
    public static function decompression($zipFile,$dstDir)
    {
        $zip = new \ZipArchive();
        $ok=$zip->open($zipFile);
        if($ok===true){
            $zip->extractTo($dstDir);
            $zip->close();
        }else{
            self::$errorMsg=$zip->getStatusString(); //错误信息
            return false;
        }
        return true;
    }

    /**
     * 解压数据-手动覆盖
     * @param $startDate
     * @param $endDate
     */
    public static function unzip($zipFile,$extractedPath)
    {
        if (empty($extractedPath) || empty($zipFile)) {
            return false;
        }
        $zip = new \ZipArchive();
        $ok=$zip->open($zipFile);
        if($ok===true){
            for($i = 0; $i < $zip->numFiles; $i++) {
                $filename = $zip->getNameIndex($i);
                $lastChar=substr($filename,-1);
                if($lastChar=="/"){
                    //目录
                    $extractedDir = rtrim($extractedPath,"/") . '/' . $filename;
                    // 确保目录存在
                    if (!is_dir($extractedDir)) {
                        mkdir($extractedDir, 0755, true);
                    }
                }else{
                    //文件
                    $extractedFile = rtrim($extractedPath,"/") . '/' . $filename;
                    // 确保目录存在
                    if (!is_dir(dirname($extractedFile))) {
                        mkdir(dirname($extractedFile), 0755, true);
                    }
                    $fromZipFile="zip://".$zipFile."#".$filename;
                    // 提取文件
                    if (!copy($fromZipFile, $extractedFile)) {
                        return false;
                    }
                }
            }
            $zip->close();
            return true;
        }else{
            return false;
        }
    }

    /**
     * 解压数据-手动覆盖[2版本]
     * @param $startDate
     * @param $endDate
     */
    public static function unzip2($zipFile,$extractedPath)
    {
        if (empty($extractedPath) || empty($zipFile)) {
            return false;
        }
        $zip = new \ZipArchive();
        $ok=$zip->open($zipFile);
        if($ok===true){
            $tmpDir=runtimePath("tmp/install");
            makeDir($tmpDir);
            $tmpName=impulseSender();
            $tmpDir=$tmpDir.$tmpName;
            $zip->extractTo($tmpDir);
            $zip->close();
            $ok=dirCopy2($tmpDir,$extractedPath);
            dirDelete2($tmpDir);
            if($ok){
                return true;
            }else{
                return false;
            }
        }else{
            return false;
        }
    }
}